#include "asgkaAdd.h"
#include "singleMember.h"
#include "asgka_space.h"
#include "asgka_network.h"
#include "messageSinglePubKey.h"
#include "messagetype.h"

#include <iostream>
using namespace std;

asgkaAdd::asgkaAdd()
{}

asgkaAdd::asgkaAdd(singleGroup *group, const std::string &name)
:asgkaBase(group),
 m_name(name)
{
}

void asgkaAdd::setNewMemberName(const std::string &name)
{
	m_name = name;
}

void asgkaAdd::computeMyDecryptKey()
{
	singleMember *pMember = m_group->getMemberByName(m_name);
	if (pMember == NULL)
	{
		cout << m_name << " is not a member of " << m_group->getGroupName() << endl;
		return ;
	}

	asgka_element oldDecKey;
	asgka_element newMemO;

	asgka_malloc(oldDecKey);
	asgka_malloc(newMemO);

	memcpy(oldDecKey, m_group->getAddrofDecryptKey(), LENGTH);
	memcpy(newMemO, pMember->getMemberXigama(m_group->getGroupName()), LENGTH);
	asgkaMulG2(m_my_decrypt_key, oldDecKey, newMemO, LENGTH);

	asgka_free(oldDecKey);
	asgka_free(newMemO);
}

void asgkaAdd::computeMyGroupKeyR()
{
	singleMember *pMember = m_group->getMemberByName(m_name);
	if (pMember == NULL)
	{
		cout << m_name << " is not a member of " << m_group->getGroupName() << endl;
		return ;
	}

	asgka_element oldGroupKeyR;
	asgka_element newSingleR;

	asgka_malloc(oldGroupKeyR);
	asgka_malloc(newSingleR);

	memcpy(oldGroupKeyR, m_group->getAddrofGroupKeyR(), LENGTH);
	memcpy(newSingleR, pMember->getMemberpubR(m_group->getGroupName()), LENGTH);
	asgkaMulG2(m_my_groupKeyR, oldGroupKeyR, newSingleR, LENGTH);

	asgka_free(oldGroupKeyR);
	asgka_free(newSingleR);
}

void asgkaAdd::computeMyGroupKeyA()
{
	singleMember *pMember = m_group->getMemberByName(m_name);
	if (pMember == NULL)
	{
		cout << m_name << " is not a member of " << m_group->getGroupName() << endl;
		return ;
	}

	asgka_element oldGroupKeyA;
	asgka_element newSingleA;

	asgka_malloc(oldGroupKeyA);
	asgka_malloc(newSingleA);

	memcpy(oldGroupKeyA, m_group->getAddrofGroupKeyA(), LENGTH);
	memcpy(newSingleA, pMember->getMemberpubA(m_group->getGroupName()), LENGTH);
	asgkaMulGT(m_my_groupKeyA, oldGroupKeyA, newSingleA, LENGTH);

	asgka_free(oldGroupKeyA);
	asgka_free(newSingleA);
}

bool asgkaAdd::sendMyPubHToNewMember()
{
	singleMember *pMember = m_group->getMemberByName(m_name);
	if (pMember == NULL)
	{
		cout << m_name << " is not a member of " << m_group->getGroupName() << endl;
		return false;
	}

	bool flag;
	asgka_element mypubH;
	asgka_malloc(mypubH);
	
	memcpy(mypubH, m_group->getAddrofPubH(), LENGTH);
	messageBase *msg = new messageSinglePubKey(m_group->getGroupName(), mypubH, NET_MESSAGE_KEY_PUB_H);
	flag = sendMessageToMember_tcp(msg, pMember);

	asgka_free(mypubH);
	return flag;
}

bool asgkaAdd::sendMyPubOToNewMember()
{
	singleMember *pMember = m_group->getMemberByName(m_name);
	if (pMember == NULL)
	{
		cout << m_name << " is not a member of " << m_group->getGroupName() << endl;
		return false;
	}

	bool flag;
	asgka_element mypubO;
	asgka_element mypriR;
	asgka_element mypriX;
	asgka_element membsH;

	asgka_malloc(mypubO);
	asgka_malloc(mypriR);
	asgka_malloc(mypriX);
	asgka_malloc(membsH);

	memcpy(mypriR, m_group->getAddrofPriR(), LENGTH);
	memcpy(mypriX, m_group->getAddrofPriX(), LENGTH);
	memcpy(membsH, pMember->getMemberpubH(m_group->getGroupName()), LENGTH);

	computeOtherPubO(mypubO, mypriX, mypriR, membsH, LENGTH);
	messageBase *msg = new messageSinglePubKey(m_group->getGroupName(), mypubO, NET_MESSAGE_KEY_PUB_O);
	flag = sendMessageToMember_tcp(msg, pMember);

	asgka_free(mypubO);
	asgka_free(mypriR);
	asgka_free(mypriX);
	asgka_free(membsH);
	return flag;
}